<?php
/**
 * code - 204xxx
 */

namespace common\service;


use common\model\ChatModel;
use common\model\ChatUnreadMessageModel;
use common\model\ChatUserModel;
use common\model\RoleModel;
use common\model\UserModel;
use support\ErrorCode;
use support\SingletonTrait;

class ChatUserService
{

    use SingletonTrait;

    private $centrifugalService;


    public function __construct()
    {
        $this->centrifugalService = CentrifugalService::getInstance();
    }


    /**
     * 更新chatUser 通过chat_global_id
     * @param $data
     * @return array
     * @throws \Exception
     */
    public function updateByChatGlobalId($data, $userId)
    {
        $chatUserModel = model(ChatUserModel::class);
        $chatGlobalId = $data['chat_global_id'];
        $oldData = $chatUserModel->where(['chat_global_id' => $chatGlobalId, 'user_id' => $userId])->find();
        if (empty($oldData)) {
            throw_strack_exception("can`t found match record", ErrorCode::MATCH_RECORD_NOT_FOUND);
        }
        $data['id'] = $oldData['id'];
        $commonService = CommonService::instance("chat_user");
        return $commonService->update($data, false);
    }

    /**
     * 邀请用户
     * @param $data
     * @return array
     * @throws \Exception
     */
    public function inviteUser($data)
    {
        $userId = $data['user_id'];
        $chatGlobalId = $data['chat_global_id'];

        $chatUserModel = model(ChatUserModel::class);
        $userModel = model(UserModel::class);

        $userData = $userModel->where(['id' => ["IN", implode(',', $userId)]])->field("id")->select();

        if (empty($userData)) {
            throw_strack_exception("can`t found user", ErrorCode::USER_NOT_FOUND);
        }
        $userId = array_column($userData, 'id', 'id');

        $chatUserData = $chatUserModel
            ->where([
                'user_id' => ["IN", implode(',', $userId)],
                'chat_global_id' => is_array($chatGlobalId) ? ["IN", $chatGlobalId] : $chatGlobalId
            ])
            ->field("id,chat_global_id,user_id,is_leave")
            ->select();

        $chatUserData = array_group_by($chatUserData, "chat_global_id");

        $needAddUser = [];
        $needUpdateUser = [];
        if (!is_array($chatGlobalId)) {
            $chatGlobalId = [$chatGlobalId];
        }
        foreach ($chatGlobalId as $chatGlobalIdItem) {
            $chatUserDataItem = $chatUserData[$chatGlobalIdItem] ?? [];
            $currentChatUserDataItem = array_column($chatUserDataItem, null, 'user_id');
            $needAddUser[$chatGlobalIdItem] = array_diff(array_keys($userId), array_keys($currentChatUserDataItem));
            $needUpdateUser = array_merge(
                $needUpdateUser,
                array_column(array_values(array_filter(array_intersect_key($currentChatUserDataItem, $userId), function ($item) {
                    return $item["is_leave"] == "yes";
                })), "id")
            );
        }

        $res = [];

        if (!empty($needUpdateUser)) {
            // 更新之前存在的用户 离开状态为no
            $res[] = $chatUserModel->where([
                "id" => ["IN", $needUpdateUser]
            ])->setField("is_leave", "no");
        }

        if (!empty($needAddUser)) {
            $dataCreate = [];
            // 添加用户
            foreach ($needAddUser as $globalId => $userData) {
                foreach ($userData as $user) {
                    $dataCreate[] = [
                        'chat_global_id' => $globalId,
                        'user_id' => $user,
                        'join_at' => time(),
                    ];
                }
            }

            if (!empty($dataCreate)) {
                $res[] = $chatUserModel->addAll($dataCreate);
            }
        }

        return $res;
    }

    /**
     * 邀请用户
     * @param $data
     * @param $currentUserId
     * @return array
     * @throws \Exception
     */
    public function inviteChatUser($data, $currentUserId)
    {
        $userId = $data['user_id'];
        $chatGlobalId = $data['chat_global_id'];

        $chatUserModel = model(ChatUserModel::class);
        $userModel = model(UserModel::class);

        $userData = $userModel->where(['id' => ["IN", implode(',', $userId)]])->field("id")->select();

        if (empty($userData)) {
            throw_strack_exception("can`t found user", ErrorCode::USER_NOT_FOUND);
        }
        $userId = array_column($userData, 'id');

        $chatUserData = $chatUserModel
            ->where([
                'user_id' => ["IN", implode(',', $userId)],
                'chat_global_id' => $chatGlobalId
            ])
            ->field("id,user_id,is_leave")
            ->select();

        $chatMap = array_column($chatUserData, null, 'user_id');


        $res = [];

        $needAddUser = array_diff($userId, array_keys($chatMap));
        $needUpdateUser = array_intersect($userId, array_keys($chatMap));
        $needUpdateUser = array_filter($needUpdateUser, function ($item) use (&$chatMap) {
            return $chatMap[$item]['is_leave'] == "yes";
        });
        $inviteUserIdList = array_merge($needAddUser, $needUpdateUser);

        if (!empty($needUpdateUser)) {
            // 更新之前存在的用户 离开状态为no
            $res[] = $chatUserModel->where([
                'chat_global_id' => $chatGlobalId,
                'user_id' => ["IN", implode(',', $needUpdateUser)],
            ])->setField("is_leave", "no");
        }

        if (!empty($needAddUser)) {
            $dataCreate = [];
            // 添加用户
            foreach ($needAddUser as $user) {
                $dataCreate[] = [
                    'chat_global_id' => $chatGlobalId,
                    'user_id' => $user,
                    'join_at' => time(),
                ];
            }

            $res[] = $chatUserModel->addAll($dataCreate);
        }

        if (!empty($inviteUserIdList)) {
            // 是否主动加入
            if (count($inviteUserIdList) == 1) {
                $inviteUserId = array_pop($inviteUserIdList);
                if ($inviteUserId == $currentUserId) {
                    // 自己主动加入 不用推送消息
                    return $res;
                } else {
                    $inviteUserIdList = [$inviteUserId];
                }
            }
            // 推送系统邀请的信息
            MessageService::getInstance()->pushInviteChatUser($chatGlobalId, $currentUserId, $inviteUserIdList);
        }
        return $res;
    }


    /**
     * 邀请用户(包含可传入部门id)
     * @param $currentUserId
     * @param $tenantId
     * @param $param
     * @return array
     * @throws \Throwable
     */
    public function inviteUsersOrDepartment($currentUserId, $tenantId, $param)
    {
        //获取邀请的用户
        $userIds = $this->getInviteUser($tenantId, $param);

        if (!empty($userIds)) {
            $userIds = array_filter($userIds, function ($item) {
                return !empty($item);
            });

            $param['data']['user_id'] = $userIds;
            unset($param['data']['receiver']);

//            $chatData = model(ChatModel::class)->field('link_type')->where(['global_id' => $param['data']['chat_global_id']])->find();
//            if (!$this->isAdmin(['chat_global_id' => $param['data']['chat_global_id'], 'user_id' => $currentUser]) && $chatData['link_type'] != 'task_work_order') {
//                throw_strack_exception("you are`nt admin,can`t invite user", ErrorCode::ONLY_ADMINISTRATORS_CAN_INVITE_USERS);
//            }
            $chat = model(ChatModel::class)->where(['global_id' => $param['data']['chat_global_id']])->find();
            $chatUserData = model(ChatUserModel::class)->where(['chat_global_id' => $param['data']['chat_global_id'], 'user_id' => $currentUserId])->find();
            if (empty($chatUserData) && $chat['link_type'] != 'task_work_order') {
                throw_strack_exception("you are`nt chat member,can`t invite user", ErrorCode::ONLY_CHAT_MEMBER_INVITE_USERS);
            }

            return $this->inviteChatUser($param['data'], $currentUserId);
        } else {
            return [];
        }
    }

    /**
     * 获取邀请的用户id
     * @param $tenantId
     * @param $param
     * @return array
     * @throws \Throwable
     */
    public function getInviteUser($tenantId, $param)
    {
        $receiver = $param['data']['receiver'];
        $receiver = array_group_by($receiver, 'type');
        $userIds = [];
        if (!empty($receiver['user'])) {
            $userIds = array_unique(array_column($receiver['user'], 'id'));
        }

        $userListIds = [];
        if (!empty($receiver['department'])) {
            $departmentData = array_column($receiver['department'], 'id');
            $userListIds = $this->getDepartmentUnderUserIds($tenantId, $departmentData);
        }

        $userIds = array_merge($userIds, $userListIds);
        return $userIds;
    }

    /**
     * 获取租户部门用户关联数据
     * @param $tenantId
     * @param $departmentData
     * @return array
     * @throws \Throwable
     */
    public function getDepartmentUnderUserIds($tenantId, $departmentData)
    {
        if (empty($departmentData)) {
            return [];
        }
        $departmentService = new DepartmentService();
        //获取部门下面的附属部门
        $departmentIds = $departmentService->getDepartmentUnderChildren($tenantId, $departmentData);
        //获取用户相关信息
        $userIds = [];
        if (!empty($departmentIds)) {
            $departmentFilter = ["IN", $departmentIds];
            $userIds = (new UserService())->getTenantDepartmentUserIds($departmentFilter, $tenantId, false);
            $userIds = array_unique($userIds);
        }

        return $userIds;
    }

    /**
     * 获取邀请的用户具体信息
     * @param $tenantId
     * @param $userIds
     * @param $departmentIds
     * @return array
     * @throws \Throwable
     */
    public function getInviteUserInfo($tenantId, $userIds = [], $departmentIds = [])
    {
        $userFilter = [];
        if (!empty($userIds)) {
            $userFilter["u.id"] = ['IN', $userIds];
        }

        $departmentFilter = [];
        if (!empty($departmentIds)) {
            $departmentService = new DepartmentService();
            //获取部门下面的附属部门
            $departmentListIds = $departmentService->getDepartmentUnderChildren($tenantId, $departmentIds);
            //获取用户相关信息

            if (!empty($departmentListIds)) {
                $departmentFilter = [
                    'd.id' => ["IN", $departmentListIds],
                    'u.is_system' => "no"
                ];
                if (!empty($tenantId)) {
                    $departmentFilter['tu.tenant_id'] = $tenantId;
                }
            }
        }

        $filter = [];
        if (!empty($departmentFilter) && !empty($userFilter)) {
            $filter = [
                [
                    $departmentFilter,
                    $userFilter,
                    "_logic" => "OR"
                ]
            ];
        } elseif (!empty($departmentFilter)) {
            $filter = $departmentFilter;
        } elseif (!empty($userFilter)) {
            $filter = $userFilter;
        }
        if (empty($filter)) {
            return [];
        }

        $rId = model(RoleModel::class)->where(['code' => 'admin'])->field('id')->find();
        $filter['r.id'] = ["neq", $rId['id']]; //暂时去除掉管理员
        $filter['_logic'] = "AND";
        $userList = (new UserService())->getUserDetailedInfo($filter);
        $userList = array_values(array_column($userList, null, 'id'));
        $userIds = array_column($userList, 'id');
        if (!empty($userIds)) {
            $avatarMap = (new UserService())->getUserAvatar($userIds);
            foreach ($userList as &$user) {
                $user['avatar'] = $avatarMap[$user['id']] ?? null;
            }
        }
        return $userList;
    }

    /**
     * 获得一个聊天成员
     * @param $filter
     * @param string $fields
     * @return mixed
     */
    public function getChatUser($filter, $fields = "*")
    {
        $model = model(ChatUserModel::class);
        return $model->where($filter)->field($fields)->find();
    }

    /**
     * 判断成员身份
     * @param $filter
     * @return mixed
     */
    public function isAdmin($filter)
    {
        $chatUserMine = $this->getChatUser($filter);
        if (empty($chatUserMine) || $chatUserMine['is_admin'] != 1) {
            return false;
        }
        return $chatUserMine;
    }

    /**
     * 移除用户
     * @param $param
     * @param int $userId
     * @return array
     * @throws \Exception
     */
    public function deleteUser($param, int $userId)
    {
        $chatData = model(ChatModel::class)->field('link_type')->where(['global_id' => $param['filter']['chat_global_id']])->find();
        if (!$this->isAdmin(['chat_global_id' => $param['filter']['chat_global_id'], 'user_id' => $userId]) && $chatData['link_type'] != 'task_work_order') {
            throw_strack_exception("you are`nt admin,can`t delete user", ErrorCode::ONLY_ADMINISTRATORS_CAN_DELETE_USERS);
        }

        return $this->deleteChatUser($param['filter'], $userId);
    }


    /**
     * 转移管理员
     * @param $data
     * @param int $userId
     * @return bool
     * @throws \Throwable
     */
    public function transferAdmin($data, int $userId)
    {
        $chatGlobalId = $data['chat_global_id'];
        $newAdminUserId = $data['user_id'];
        $chatUserModel = model(ChatUserModel::class);

        //身份判断
        if (!$this->isAdmin(['user_id' => $userId, 'chat_global_id' => $chatGlobalId])) {
            throw_strack_exception("you are`nt admin", ErrorCode::YOU_ARE_NOT_AN_ADMINISTRATOR);
        }

        //目标用户是否在会话中
        $newAdminChatUserData = $this->getChatUser(['chat_global_id' => $chatGlobalId, 'user_id' => $newAdminUserId], 'id');

        if (empty($newAdminChatUserData)) {
            throw_strack_exception("user you want to transfer is not exist", ErrorCode::TRANSFER_USER_IS_NOT_EXIST);
        }

        $chatUserModel->startTrans();
        try {
            $chatUserModel->where(['chat_global_id' => $chatGlobalId, 'user_id' => $userId])->setField("is_admin", 0);
            $chatUserModel->where(['id' => $newAdminChatUserData['id']])->setField("is_admin", 1);
            //发送消息
            (new MessageService())->pushTransferAdminMessage($userId, $newAdminUserId, $chatGlobalId);

            $chatUserModel->commit();
            return true;
        } catch (\Throwable $e) {
            $chatUserModel->rollback();
            throw $e;
        }
    }

    /**
     * 删除并推出
     * @param $param
     * @param int $userId
     * @return bool|int|string
     * @throws \Exception
     */
    public function deleteAndExit($param, int $userId)
    {
        $filter = $param['filter'];
        $filter['user_id'] = $userId;
        $chatGlobalId = $filter['chat_global_id'];


        $chatUserMine = $this->getChatUser($filter);
        if (empty($chatUserMine)) {
            throw_strack_exception("you don`t belong this chat", ErrorCode::NOT_BELONG_THIS_CHAT);
        }
        if ($chatUserMine['is_admin'] == 1) {
            throw_strack_exception("admin can`t exist chat,need transfer admin first", ErrorCode::ADMINISTRATOR_NEEDS_TO_BE_TRANSFERRED_FIRST);
        }

        $count = model(ChatUserModel::class)->where($filter)->save(["is_leave" => "yes"]);

        (new MessageService())->pushDeleteAndExitMessage($userId, $chatGlobalId);

        return $count;
    }

    /**
     * 删除会话用户
     * @param $filter
     * @return int
     */
    public function deleteWithOutAuth($filter)
    {
        $chatUsers = model(ChatUserModel::class)->where($filter)->field("id")->select();
        if (empty($chatUsers)) {
            return 0;
        }
        return model(ChatUserModel::class)->where(['id' => ['IN', array_column($chatUsers, 'id')]])->setField("is_leave", "yes");
    }


    /**
     * 删除会话用户
     * @param $filter
     * @param $adminUser
     * @return array
     * @throws \Exception
     */
    public function deleteChatUser($filter, $adminUser)
    {
        $chatGlobalId = $filter['chat_global_id'];

        $chatUsers = model(ChatUserModel::class)->where([
            'chat_global_id' => $chatGlobalId,
            'user_id' => $filter['user_id']
        ])->field("id,chat_global_id,user_id")->select();

        $res = [];

        if (!empty($chatUsers)) {
            $chatUsersIds = array_column($chatUsers, 'user_id');

            $channelList = model(ChatUserModel::class)
                ->alias('cu')
                ->join('user AS u ON cu.user_id = u.id', "LEFT")
                ->field('u.channel,cu.user_id,u.id')
                ->where(['chat_global_id' => $chatGlobalId, 'cu.is_leave' => "no"])
                ->select();
            $res = model(ChatUserModel::class)->where(['chat_global_id' => $chatGlobalId, 'user_id' => ['IN', $chatUsersIds]])->save(["is_leave" => "yes"]);

            //推送消息
            (new MessageService())->pushDeleteChatUseMessage($adminUser, $chatGlobalId, $chatUsersIds, $channelList);

            //清除掉被踢出的用户的未读消息
            if (!empty($chatUsersIds)) {
                model(ChatUnreadMessageModel::class)->where(['chat_global_id' => $chatGlobalId, 'user_id' => ['IN', $chatUsersIds]])->delete();
            }
        }

        return $res;
    }

    /**
     * 添加多个会话多个用户
     * @param $data
     * @return array
     * @throws \Exception
     */
    public function addMultipleUser($data)
    {
        $result = [];
        foreach (array_chunk($data, 500) as $dataItem) {
            $result[] = model(ChatUserModel::class)->addAll($dataItem);
        }
        return $result;
    }
}
